// -----------------------------------------------------------------------------
// M A R I T I M E   R E S E A R C H   I N S T I T U T E   N E T H E R L A N D S
// -----------------------------------------------------------------------------
// Program  : mermaid
// Module   : interactive waves
// File     : PulseControl.cpp
// -----------------------------------------------------------------------------
// Revisions:
// December 12, 2008  asicherer
// -----------------------------------------------------------------------------


#ifndef PULSECONTROL_H
#define PULSECONTROL_H

#include <deque>
#include <mml/Vector.h>
#include <mml/Matrix.h>
#include "defines.h"
#include "Array2D.h"

class FileReader;
class Geometry;
class GeometryManager;
class PulseManager;

/// class for handling all pressure pulses
class PulseControl
{

public:
    
    /// 2D coordinate
    struct Point
    {
        REAL x1; ///< x1 (x) direction
        REAL x2; ///< x2 (y) direction
        /// constructor
        Point()               : x1(0), x2(0) {}
        /// constructor
        Point(REAL a, REAL b) : x1(a), x2(b) {}
    };
    /// list of 2D coordinates
    typedef std::deque<Point> Waypoints;

    PulseControl(int steps,
                 REAL timestep,
                 int Nx1,
                 int Nx2,
                 REAL dx1,
                 REAL dx2,
                 REAL pstart);
    
    virtual ~PulseControl();
    
    bool setupPulses(FileReader &fr);
    bool setupPaths(FileReader &fr);

    unsigned int getNumberOfPulses() const;
    bool getStartVector(int ship, Point *pstart, Point *pend);
    const Waypoints &getWaypoints(int ship);
    const Waypoints &getPath(int ship);
    
    void toggleMovement();

    void startLowering(REAL currenttime);

    void movePulses(REAL currenttime);

    void computePulsePattern(REAL currenttime, REAL dt, const Array2D<REAL>* pNetHeight,
                             Array2D<REAL> **ppPressurePattern);

    const Geometry* getGeometry(int nr) const;

private:

    struct PulseData
    {
        mml::Vector3d m_speed; ///< initial velocity vector
        REAL m_scalarSpeed;    ///< scalar velocity of pressure pulses
        REAL m_currentScalarSpeed; ///< current scalar velocity of pressure pulses
        mml::Vector3d m_acceleration; ///< initial acceleration vector
        REAL m_scalarAcceleration; ///< scalar acceleration of pressure pulse
        REAL m_currentScalarAcceleration; ///< current scalar acceleration of pressure pulse
        PulseData(const mml::Vector3d& speed, REAL scalarSpeed,
            const mml::Vector3d& acceleration, REAL scalarAcceleration)
        : m_speed(speed), 
          m_scalarSpeed(scalarSpeed), m_currentScalarSpeed(scalarSpeed),
          m_acceleration(acceleration),
          m_scalarAcceleration(scalarAcceleration), m_currentScalarAcceleration(scalarAcceleration) 
        {}
    };

    void computeFirstWaypoint(int ship);
    void computePath(int ship);

    bool m_smoothing; ///< spatial smoothing of prerssure pulses
    int m_steps; ///< number of simulation steps
    REAL m_timestep; ///< length of one simulation step in seconds
    REAL m_previoustime; ///< previous time step
    int m_currentPoint[NRP]; ///< index of current point in path list
    Waypoints m_waypoints[NRP]; ///< manually marked waypoints of path
    Waypoints m_path[NRP]; ///< interpolated path points
    std::vector<PulseData> m_pulseData; ///< velocities etc
    PulseManager* m_pPulseManager;
    GeometryManager* m_pGeometryManager;
    bool m_moving;
};

#endif // PULSECONTROL_H
